"""
爬虫服务API主应用
集成热点数据API和任务控制API
"""
from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, RedirectResponse
from contextlib import asynccontextmanager
import uvicorn
import logging
import time
import redis
import os
from datetime import datetime
from typing import Optional

from .hot_data import router as hot_data_router
from .task_control import router as task_control_router
from .task_status import router as task_status_router
from .cleaning_config import router as cleaning_router

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 导入配置
from .config import settings

# Redis客户端（用于限流）
redis_client = redis.Redis(
    host=settings.redis_host,
    port=settings.redis_port,
    password=settings.redis_password,
    db=settings.redis_rate_limit_db,
    decode_responses=True
)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动时
    logger.info("Crawler API service starting...")
    
    # 初始化MongoDB索引
    from .mongodb_indexes import init_indexes_on_startup
    await init_indexes_on_startup()
    
    # 启动数据同步调度器
    from .scheduler import scheduler
    scheduler.start()
    logger.info("Data sync scheduler started")
    
    # 启动时立即同步一次数据
    try:
        await scheduler.sync_all_platforms()
    except Exception as e:
        logger.error(f"Initial data sync failed: {e}")
    
    yield
    
    # 关闭时
    scheduler.stop()
    logger.info("Crawler API service shutting down...")


def create_application() -> FastAPI:
    """创建FastAPI应用实例"""
    app = FastAPI(
        title="热点数据爬虫API",
        description="提供多平台热点数据的查询、搜索、趋势分析和聚合功能，以及爬虫任务控制",
        version="1.0.0",
        docs_url="/api/docs",
        redoc_url="/api/redoc",
        openapi_url="/api/openapi.json",
        lifespan=lifespan,
        redirect_slashes=False  # 禁用自动斜杠重定向
    )
    
    # CORS配置 - 开发环境允许所有来源，使用最宽松的配置
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],  # 允许所有来源
        allow_credentials=False,  # 禁用凭证以避免冲突
        allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH"],
        allow_headers=["*"],
        expose_headers=["*"],
        max_age=3600,  # 预检缓存时间
    )
    
    # 注册路由
    app.include_router(hot_data_router)
    app.include_router(task_control_router)
    app.include_router(task_status_router)
    app.include_router(cleaning_router)
    
    return app


app = create_application()


# JWT认证依赖（完整实现）
async def verify_token(request: Request) -> Optional[str]:
    """验证JWT token"""
    from .auth import verify_jwt_token
    
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        return None
    
    try:
        token = auth_header.split(" ")[1]
        # 使用auth模块中的JWT验证
        token_data = verify_jwt_token(token)
        if token_data:
            return token_data.sub
    except Exception as e:
        logger.warning(f"Token verification failed: {e}")
    
    return None


# 认证中间件
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
    """认证中间件"""
    # 跳过OPTIONS预检请求（CORS）
    if request.method == "OPTIONS":
        return await call_next(request)
    
    # 跳过文档端点的认证
    if request.url.path in ["/api/docs", "/api/redoc", "/api/openapi.json", "/health"]:
        return await call_next(request)
    
    # 跳过热点数据API的认证（公开API）
    if request.url.path.startswith("/api/v1/hot-items"):
        return await call_next(request)
    
    # 验证token - 暂时禁用认证以进行开发测试
    user = await verify_token(request)
    # 将认证检查临时禁用
    # if not user and os.getenv("REQUIRE_AUTH", "false").lower() == "true":
    #     return JSONResponse(
    #         status_code=401,
    #         content={
    #             "success": False,
    #             "error": {
    #                 "code": "UNAUTHORIZED",
    #                 "message": "Authentication required",
    #                 "timestamp": datetime.utcnow().isoformat()
    #             }
    #         }
    #     )
    
    # 添加用户信息到请求
    request.state.user = user
    return await call_next(request)


# 限流中间件
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
    """限流中间件"""
    # 跳过OPTIONS预检请求（CORS）
    if request.method == "OPTIONS":
        return await call_next(request)
    
    # 跳过文档端点
    if request.url.path in ["/api/docs", "/api/redoc", "/api/openapi.json"]:
        return await call_next(request)
    
    # 获取客户端IP
    client_ip = request.client.host
    endpoint = request.url.path
    
    # 限流键
    rate_limit_key = f"rate_limit:{client_ip}:{endpoint}"
    
    try:
        # 检查限流
        current = redis_client.get(rate_limit_key)
        if current:
            count = int(current)
            if count >= int(os.getenv("RATE_LIMIT_PER_MINUTE", 60)):
                return JSONResponse(
                    status_code=429,
                    content={
                        "success": False,
                        "error": {
                            "code": "RATE_LIMIT_EXCEEDED",
                            "message": "Too many requests",
                            "timestamp": datetime.utcnow().isoformat()
                        }
                    }
                )
            redis_client.incr(rate_limit_key)
        else:
            redis_client.setex(rate_limit_key, 60, 1)
    except Exception as e:
        logger.warning(f"Rate limit check failed: {e}")
    
    return await call_next(request)


# 请求日志中间件
@app.middleware("http")
async def logging_middleware(request: Request, call_next):
    """请求日志记录"""
    start_time = time.time()
    
    # 记录请求
    logger.info(f"Request: {request.method} {request.url.path}")
    
    response = await call_next(request)
    
    # 记录响应
    process_time = time.time() - start_time
    logger.info(
        f"Response: {request.method} {request.url.path} - "
        f"Status: {response.status_code} - Time: {process_time:.3f}s"
    )
    
    # 添加处理时间头
    response.headers["X-Process-Time"] = str(process_time)
    
    return response


# 错误处理
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    """HTTP异常处理"""
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "success": False,
            "error": {
                "code": f"HTTP_{exc.status_code}",
                "message": exc.detail,
                "timestamp": datetime.utcnow().isoformat(),
                "path": str(request.url)
            }
        }
    )


@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
    """通用异常处理"""
    logger.error(f"Unhandled exception: {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={
            "success": False,
            "error": {
                "code": "INTERNAL_SERVER_ERROR",
                "message": "An internal error occurred",
                "timestamp": datetime.utcnow().isoformat(),
                "path": str(request.url)
            }
        }
    )


# 健康检查端点
@app.get("/health")
async def health_check():
    """健康检查"""
    try:
        # 检查Redis连接
        redis_client.ping()
        redis_status = "healthy"
    except:
        redis_status = "unhealthy"
    
    return {
        "status": "healthy" if redis_status == "healthy" else "degraded",
        "timestamp": datetime.utcnow().isoformat(),
        "services": {
            "api": "healthy",
            "redis": redis_status
        }
    }

# CORS测试端点
@app.get("/api/v1/cors-test")
async def cors_test():
    """CORS测试端点"""
    return {
        "message": "CORS test successful",
        "timestamp": datetime.utcnow().isoformat(),
        "origin": "backend"
    }


# 根路径重定向到文档
@app.get("/")
async def root():
    """根路径"""
    return {
        "message": "Crawler API Service",
        "version": "1.0.0",
        "docs": "/api/docs",
        "redoc": "/api/redoc"
    }


if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=int(os.getenv("API_PORT", 8001)),
        reload=os.getenv("DEBUG", "false").lower() == "true"
    )